﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Web.Mvc;
using System.Web.UI;

using ProjectBase.Core;
using ProjectBase.Core.Utils;
using ProjectBase.Core.Web;

namespace ProjectBase.Mvc
{
    public abstract class ControlHtml<TModel> : ControlHtml, IVisualControl
        where TModel : class, ICoreModel
    {
        #region IVisualControl
        void IVisualControl.BuildControls()
        {
            BuildControls();
        }
        void IVisualControl.SetViewData(ViewDataDictionary viewData)
        {
            SetViewData(viewData);
        }

        void IVisualControl.AsReadOnly()
        {
            AsReadOnly();
        }
        VisualControlCollection IVisualControl.Controls
        {
            get { return Controls; }
        }
        AttributeCollection IVisualControl.Attributes
        {
            get { return Attributes; }
        }
        #endregion IVisualControl

        #region Model init
        protected override void SetChildControl(IVisualControl childControl)
        {
            base.SetChildControl(childControl);
            childControl.SetViewData(new ViewDataDictionary(GetModel(Model, childControl.ViewDataKey)));
        }
        protected ICoreModel GetModel(TModel model, string viewDataKey)
        {
            if (viewDataKey.IsEmpty())
            {
                return model;
            }
            ICoreModel nested;
            if (model.TryFindProperty(viewDataKey, out nested))
            {
                return nested;
            }
            return null;
        }

        protected virtual void SetViewData(ViewDataDictionary viewData)
        {
            ViewData = new ViewDataDictionary<TModel>(viewData);
        }
        #endregion Model init

        #region properties
        public ViewDataDictionary<TModel> ViewData { get; set; }
        public virtual TModel Model { get { return ViewData.Model; } }
        #endregion properties
    }

    public abstract class ControlHtml
    {
        #region members
        static readonly object Locker = new object();
        static event PreRenderControlEventHandler PreRenderControlHandler;
        AttributeCollection _attributes;
        VisualControlCollection _controls;
        #endregion members

        #region properties
        public virtual string ID { get; set; }
        public virtual IUrlHelper Url { get; set; }
        public virtual HtmlHelper Html { get; set; }
        public virtual ViewContext ViewContext { get; set; }
        public virtual string ViewDataKey { get; set; }
        public VisualControlCollection Controls { get { return _controls ?? (_controls = new VisualControlCollection()); } }

        protected AttributeCollection Attributes { get { return _attributes ?? (_attributes = new AttributeCollection(new StateBag())); } }
        protected virtual string TagName { get { return string.Empty; } }
        public static event PreRenderControlEventHandler PreRenderControl
        {
            add
            {
                if (!value.Method.IsStatic)
                {
                    return;
                }
                lock (Locker)
                {
                    PreRenderControlHandler += value;
                }
            }
            remove
            {
                lock (Locker)
                {
                    PreRenderControlHandler -= value;
                }
            }
        }
        #endregion properties

        #region Init Control
        protected virtual void SetChildControl(IVisualControl child)
        {
            child.Url = Url;
            child.Html = Html;
            child.ViewContext = ViewContext;
        }
        protected virtual void AsReadOnly()
        {
            var readOnlyControl = this as IHaveReadOnlyMode;
            if (readOnlyControl.Is())
            {
                readOnlyControl.ShowReadOnly = true;
            }

            foreach (var control in Controls)
            {
                control.AsReadOnly();
            }
        }

        protected virtual void BuildControls()
        {
            if (PreRenderControlHandler.IsNull())
            {
                return; // no listeners
            }
            var args = new PreRenderControlEventArgs {ViewContext = ViewContext};
            PreRenderControlHandler(this, args);

            if (args.UseReadOnly)
            {
                AsReadOnly();
            }
        }

        protected virtual void InitControls()
        {
            foreach (var c in Controls)
            {
                SetChildControl(c);

                c.BuildControls();
            }
        }
        #endregion Init Control

        #region Render Control

        public virtual void RenderControl(HtmlTextWriter writer)
        {
            if (PreRenderControlHandler.Is())
            {
                // pass PreRenderControlEventArgs to listeners
                var args = new PreRenderControlEventArgs { ViewContext = ViewContext };
                PreRenderControlHandler(this, args);

                // skip rendering
                if (args.DoNotRender)
                {
                    return;
                }
            }

            // init children
            InitControls();

            // render
            RenderBeginTag(writer);
            RenderChildren(writer);
            RenderEndTag(writer);
        }

        protected virtual void RenderBeginTag(HtmlTextWriter writer)
        {
            if (TagName.IsEmpty())
            {
                return;
            }
            writer.Write(Environment.NewLine);
            writer.WriteBeginTag(TagName);
            Attributes.Render(writer);
            writer.Write(HtmlTextWriter.TagRightChar);
        }

        protected virtual void RenderChildren(HtmlTextWriter writer)
        {
            foreach (IVisualControl control in Controls)
            {
                RenderChild(writer, control);
            }
        }

        protected virtual void RenderEndTag(HtmlTextWriter writer)
        {
            if (TagName.IsNotEmpty())
            {
                writer.WriteEndTag(TagName);
            }
        }

        protected virtual void RenderChild(HtmlTextWriter writer, IVisualControl control)
        {
            control.RenderControl(writer);
        }
        #endregion Render Control
    }
}
